﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using OpenLS.Spreadsheet.Formats.Biff;
using OpenLS.Spreadsheet.Formats.Biff.Records;

namespace OpenLS.Spreadsheet.Formats
{
#if DEBUG
    partial class BiffFormat
    {
        public void OutputBytes(string sourceFileName, string destinationFileName)
        {
            FormulaTokenFactory.TestTokens();
         //   using (Storage destinationStorage = Storage.Create(destinationFileName))
            {
                using (
                    var storage = Storage.Open(sourceFileName))
                {
                    Stream stream = null;
                    try
                    {
                        stream = storage.OpenStream("Workbook", FileAccess.Read);
                    }
                    catch (COMException e)
                    {
                        if (stream != null)
                            stream.Dispose();
                        throw new ApplicationException("Unable to find workbook stream", e);
                    }
                    long l = stream.Length;
                    var bytes = new byte[l];
                    stream.Read(bytes, 0, (int)l);
                    using (TextWriter writer = new StreamWriter(destinationFileName))
                    {
                        int i = 0;
                        foreach (byte b in bytes)
                        {
                            writer.Write(b);
                            writer.Write(", ");
                            if (i % 10 == 0)
                            {
                                writer.WriteLine("");
                                writer.Write(i.ToString() + " :: ");
                            }
                            i++;
                        }
                    }
                }

            }
        }
        public void FilterXlsToXls(string sourceFileName, string destinationFileName)
        {
            using (Storage destinationStorage = Storage.Create(destinationFileName))
            {
                using (
                    var storage = Storage.Open(sourceFileName))
                {
                    Stream stream = null;
                    try
                    {
                        stream = storage.OpenStream("Workbook", FileAccess.Read);
                    }
                    catch (COMException e)
                    {
                        if (stream != null)
                            stream.Dispose();
                        throw new ApplicationException("Unable to find workbook stream", e);
                    }
                    long l = stream.Length;
                    var bytes = new byte[l];
                    stream.Read(bytes, 0, (int)l);
                    var mStream = new MemoryStream(bytes);
                    var reader = new BiffRecordReader(new BiffReaderContext(new BinaryReader(mStream)));
                    {
                        using (Stream stream2 = destinationStorage.CreateStream("Workbook", FileAccess.ReadWrite))
                        {
                            var mStream2 = new MemoryStream();
                            byte[] data2;
                            using (var writer = new BinaryWriter(mStream2))
                            {
                                BiffWriterWorkbookContext ctx = new BiffWriterWorkbookContext(null, writer);

                                foreach (var record in reader.GetRecords())
                                {
                                    if (GetRecordImportance(record) == RecordImportance.Unnecessary)
                                    {
                                        continue;
                                    }
                                    if (record is IgnoredBiffRecord)
                                    {
                                     //   Debug.WriteLine("Ignored " + record + "   " + record.RecordType + " " + (int)record.RecordType);
                                    } 
                                    if (record is ObjRecord)
                                    {
                                        ctx.AddObjRecord((ObjRecord) record);
                                       //\\ continue;
                                    }
                                    if (record is MsoDrawingRecord)
                                    {
                                        MsoDrawingRecord msoDrawingRecord = (MsoDrawingRecord) record;
                                    }
                                    record.Write(ctx);
                                }
                                mStream2.Flush();
                                data2 = new byte[mStream2.Length];
                                mStream2.Position = 0;
                                mStream2.Read(data2, 0, data2.Length);
                            }
                            stream2.Write(data2, 0, data2.Length);
                        }
                    }

                }

            }
        }
        enum RecordImportance
        {
            Unknown,
            Necessary,
            Unnecessary,

        }

        private RecordImportance GetRecordImportance(BiffRecord record)
        {
            
            return RecordImportance.Necessary;
        }
        static Dictionary<BiffRecordType, bool> dictionary = new Dictionary<BiffRecordType, bool>();

        public void OutputRecords(string sourceFileName, string destinationFileName, bool withRecordId)
        {
            using (StreamWriter writer = new StreamWriter(destinationFileName))
            {
                try
                {
                    using (
                        var storage = Storage.Open(sourceFileName))
                    {
                        Stream stream = null;
                        try
                        {
                            stream = storage.OpenStream("Workbook", FileAccess.Read);
                        }
                        catch (COMException e)
                        {
                            if (stream != null)
                                stream.Dispose();
                            throw new ApplicationException("Unable to find workbook stream", e);
                        }
                        long l = stream.Length;
                        var bytes = new byte[l];
                        stream.Read(bytes, 0, (int)l);
                        var mStream = new MemoryStream(bytes);
                        var reader = new BiffRecordReader(new BiffReaderContext(new BinaryReader(mStream)));
                        {
                            int recordId = 0;
                            BiffRecord previousRecord = new BofRecord(BofRecord.BofRecordType.Chart);
                            foreach (var record in reader.getAllRecords())
                            {
                                if (GetRecordImportance(record) == RecordImportance.Unnecessary)
                                    continue;

                                try
                                {
                                    if (record.GetType() != previousRecord.GetType())
                                        recordId = 0;
                                    if (withRecordId)
                                        writer.Write(string.Format("{0:D6}", recordId) + " :: ");
                                    writer.WriteLine(record.ToString());
                                    recordId++;
                                    previousRecord = record;


                                }
                                catch (Exception exp)
                                {
                                    writer.WriteLine(exp);
                                    break;
                                }
                            }
                        }
                    }
                }
                catch (Exception exp)
                {
                    writer.WriteLine(exp.ToString());
                }
            }
        }

        public void TransformXlsToXls(string sourceFileName, string destinationFileName)
        {
            using (Storage destinationStorage = Storage.Create(destinationFileName))
            {
                using (
                    var storage = Storage.Open(sourceFileName))
                {
                    Stream stream = null;
                    try
                    {
                        stream = storage.OpenStream("Workbook", FileAccess.Read);
                    }
                    catch (COMException e)
                    {
                        if (stream != null)
                            stream.Dispose();
                        throw new ApplicationException("Unable to find workbook stream", e);
                    }
                    long l = stream.Length;
                    var bytes = new byte[l];
                    stream.Read(bytes, 0, (int)l);
                    var mStream = new MemoryStream(bytes);
                    var reader = new BiffRecordReader(new BiffReaderContext(new BinaryReader(mStream)));
                    {
                        using (Stream stream2 = destinationStorage.CreateStream("Workbook", FileAccess.ReadWrite))
                        {
                            var mStream2 = new MemoryStream();
                            byte[] data2;
                            using (var writer = new BinaryWriter(mStream2))
                            {
                                BiffWriterWorkbookContext ctx = new BiffWriterWorkbookContext(null, writer);
                                List<BiffRecord> records = new List<BiffRecord>(reader.GetRecords());
                                foreach (var record in records)
                                {
                                    if (record is XfcrcRecord)
                                    {
                                        XfcrcRecord xfcrcRecord = (XfcrcRecord) record;
                                       //    continue;
                                        xfcrcRecord.SetCrc(Enumerable.OfType<XFRecord>(records));
                                    }
                                    record.Write(ctx);
                                }
                                mStream2.Flush();
                                data2 = new byte[mStream2.Length];
                                mStream2.Position = 0;
                                mStream2.Read(data2, 0, data2.Length);
                            }
                            stream2.Write(data2, 0, data2.Length);
                        }
                    }

                }

            }
        }

        public void CopyXlsToXls(string sourceFileName, string destinationFileName)
        {
            using (Storage destinationStorage = Storage.Create(destinationFileName))
            {
                using (
                    var storage = Storage.Open(sourceFileName))
                {
                    Stream stream = null;
                    try
                    {
                        stream = storage.OpenStream("Workbook", FileAccess.Read);
                    }
                    catch (COMException e)
                    {
                        if (stream != null)
                            stream.Dispose();
                        throw new ApplicationException("Unable to find workbook stream", e);
                    }
                    long l = stream.Length;
                    var bytes = new byte[l];
                    stream.Read(bytes, 0, (int)l);
                    var mStream = new MemoryStream(bytes);
                    {
                        using (Stream stream2 = destinationStorage.CreateStream("Workbook", FileAccess.ReadWrite))
                        {
                            var mStream2 = new MemoryStream();
                            byte[] data2;
                            stream2.Write(bytes, 0, bytes.Length);
                        }
                    }

                }

            }
        }

        public void OutputRawRecords(string fileName)
        {
            using (
                var storage = Storage.Open(fileName))
            {
                Stream stream = null;
                try
                {
                    stream = storage.OpenStream("Workbook", FileAccess.Read);
                }
                catch (COMException e)
                {
                    if (stream != null)
                        stream.Dispose();
                    throw new ApplicationException("Unable to find workbook stream", e);
                }
                using (var w = new StreamWriter(fileName + ".binrecords"))
                {
                    long l = stream.Length;
                    var bytes = new byte[l];
                    stream.Read(bytes, 0, (int) l);
                    var mStream = new MemoryStream(bytes);
                    BinaryReader binaryReader = new BinaryReader(mStream);
                    var reader = new BiffRecordReader(new BiffReaderContext(binaryReader));
                    long previousPosition = 0;
                    foreach (var record in reader.GetRecords())
                    {
                        w.WriteLine(record.GetType().Name);
                        long nextPosition = previousPosition + record.Length + 4;
                        for (var pos = previousPosition; pos < nextPosition; pos++)
                            w.Write(bytes[pos].ToString() + ",");
                        previousPosition = nextPosition;
                    }
                }
            }
        }
        public IEnumerable<BiffRecord> GetRecords(string fileName)
        {
            using (
                var storage = Storage.Open(fileName))
            {
                Stream stream = null;
                try
                {
                    stream = storage.OpenStream("Workbook", FileAccess.Read);
                }
                catch (COMException e)
                {
                    if (stream != null)
                        stream.Dispose();
                    throw new ApplicationException("Unable to find workbook stream", e);
                }
                long l = stream.Length;
                var bytes = new byte[l];
                stream.Read(bytes, 0, (int) l);
                var mStream = new MemoryStream(bytes);
                var reader = new BiffRecordReader(new BiffReaderContext(new BinaryReader(mStream)));
                return reader.GetRecords();
            }
        }

    }
#endif
}